/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*
*/
/*
File:       TCPSocket.h

Contains:   TCP socket object




*/

#ifndef __TCPSOCKET_H__
#define __TCPSOCKET_H__

#include <stdio.h>
#include <stdlib.h>
#ifndef __Win32__
#include <sys/types.h>
#include <sys/socket.h>
#endif

#include "Socket.h"

class TCPSocket : public Socket
{
public:

    //TCPSocket takes an optional task object which will get notified when
    //certain events happen on this socket. Those events are:
    //
    //S_DATA:               Data is currently available on the socket.
    //S_CONNECTIONCLOSING:  Client is closing the connection. No longer necessary
    //                      to call Close or Disconnect, Snd & Rcv will fail.
    TCPSocket(UInt32 inSocketType)
        : Socket(inSocketType){}
    virtual ~TCPSocket() {}

    //Open
    OS_Error    Open() { return Socket::Open(SOCK_STREAM); }

    // Connect. Attempts to connect to the specified remote host. If this
    // is a non-blocking socket, this function may return EINPROGRESS, in which
    // case caller must wait for either an EV_RE or an EV_WR. You may call
    // CheckAsyncConnect at any time, which will return OS_NoErr if the connect
    // has completed, EINPROGRESS if it is still in progress, or an appropriate error
    // if the connect failed.
    OS_Error    Connect(UInt32 inRemoteAddr, UInt16 inRemotePort);
    OS_Error    Connect(const char* inRemoteAddr, UInt16 inRemotePort);
    //OS_Error  CheckAsyncConnect();

    // Basically a copy constructor for this object, also NULLs out the data
    // in tcpSocket.        
    void        SnarfSocket(TCPSocket & tcpSocket);

    //ACCESSORS:
    //Returns NULL if not currently available.

    UInt32      GetRemoteAddr() { return ntohl(fRemoteAddr.sin_addr.s_addr); }

    //host order
    UInt32      GetRemoteAddrHostOrder() { return fRemoteAddr.sin_addr.s_addr; }
    UInt16      GetRemotePort() { return ntohs(fRemoteAddr.sin_port); }
    //This function is NOT thread safe!
    char*  GetRemoteAddrStr();

    void        Set(int inSocket, struct sockaddr_in* remoteaddr);
	OS_Error    SendTo(void* inBuffer, UInt32 inLength);
	OS_Error    RecvFrom(void* ioBuffer, UInt32 inBufLen, UInt32* outRecvLen);
protected:


    enum
    {
        kIPAddrBufSize = 20 //UInt32
    };

    struct sockaddr_in  fRemoteAddr;
    char fRemoteBuffer[kIPAddrBufSize];


    friend class TCPListenerSocket;
};
#endif // __TCPSOCKET_H__

